import logging
import os
import sys
from datetime import datetime
from typing import Optional, Dict, Any

class Logger:
    """
    统一的日志管理类
    支持不同级别的日志记录，自动创建日志文件，支持控制台和文件双重输出
    """
    
    _instance = None
    _initialized = False
    
    def __new__(cls, *args, **kwargs):
        """单例模式，确保只有一个日志实例"""
        if cls._instance is None:
            cls._instance = super(Logger, cls).__new__(cls)
        return cls._instance
    
    def __init__(self, 
                 name: str = "LongNovel",
                 log_file: str = "app.log",
                 level: int = logging.INFO,
                 max_bytes: int = 10 * 1024 * 1024,  # 10MB
                 backup_count: int = 5,
                 console_output: bool = True,
                 file_output: bool = True):
        """
        初始化日志器
        
        Args:
            name: 日志器名称
            log_file: 日志文件路径
            level: 日志级别
            max_bytes: 单个日志文件最大大小
            backup_count: 备份文件数量
            console_output: 是否输出到控制台
            file_output: 是否输出到文件
        """
        if self._initialized:
            return
            
        self.name = name
        self.log_file = log_file
        self.level = level
        self.max_bytes = max_bytes
        self.backup_count = backup_count
        self.console_output = console_output
        self.file_output = file_output
        
        # 创建日志器
        self.logger = logging.getLogger(name)
        self.logger.setLevel(level)
        
        # 清除已有的处理器
        self.logger.handlers.clear()
        
        # 设置格式
        formatter = logging.Formatter(
            '%(asctime)s [%(levelname)s] %(name)s: %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S'
        )
        
        # 添加控制台处理器
        if console_output:
            console_handler = logging.StreamHandler(sys.stdout)
            console_handler.setLevel(level)
            console_handler.setFormatter(formatter)
            self.logger.addHandler(console_handler)
        
        # 添加文件处理器
        if file_output:
            # 确保日志目录存在
            log_dir = os.path.dirname(log_file)
            if log_dir and not os.path.exists(log_dir):
                os.makedirs(log_dir)
            
            # 使用 RotatingFileHandler 进行日志轮转
            from logging.handlers import RotatingFileHandler
            file_handler = RotatingFileHandler(
                log_file,
                maxBytes=max_bytes,
                backupCount=backup_count,
                encoding='utf-8'
            )
            file_handler.setLevel(level)
            file_handler.setFormatter(formatter)
            self.logger.addHandler(file_handler)
        
        self._initialized = True
    
    def debug(self, message: str, **kwargs):
        """记录调试信息"""
        self._log(logging.DEBUG, message, **kwargs)
    
    def info(self, message: str, **kwargs):
        """记录一般信息"""
        self._log(logging.INFO, message, **kwargs)
    
    def warning(self, message: str, **kwargs):
        """记录警告信息"""
        self._log(logging.WARNING, message, **kwargs)
    
    def error(self, message: str, **kwargs):
        """记录错误信息"""
        self._log(logging.ERROR, message, **kwargs)
    
    def critical(self, message: str, **kwargs):
        """记录严重错误信息"""
        self._log(logging.CRITICAL, message, **kwargs)
    
    def exception(self, message: str, **kwargs):
        """记录异常信息（包含堆栈跟踪）"""
        self._log(logging.ERROR, message, exc_info=True, **kwargs)
    
    def _log(self, level: int, message: str, **kwargs):
        """内部日志记录方法"""
        # 如果有额外参数，格式化消息
        if kwargs:
            message = f"{message} | {kwargs}"
        
        self.logger.log(level, message)
    
    def log_request(self, method: str, url: str, status_code: int, duration: float, **kwargs):
        """记录HTTP请求信息"""
        message = f"HTTP {method} {url} - {status_code} ({duration:.3f}s)"
        self.info(message, **kwargs)
    
    def log_api_call(self, model: str, tokens: int, cost: float, currency: str, **kwargs):
        """记录API调用信息"""
        message = f"API调用 {model} - Tokens: {tokens}, 费用: {cost:.4f}{currency}"
        self.info(message, **kwargs)
    
    def log_error_with_context(self, error: Exception, context: str = "", **kwargs):
        """记录带上下文的错误信息"""
        error_type = type(error).__name__
        error_msg = str(error)
        message = f"错误 [{error_type}] {error_msg}"
        if context:
            message = f"{context}: {message}"
        
        self.error(message, **kwargs)
        self.exception(message, **kwargs)
    
    def log_performance(self, operation: str, duration: float, **kwargs):
        """记录性能信息"""
        message = f"性能 {operation} - 耗时: {duration:.3f}s"
        self.info(message, **kwargs)
    
    def log_user_action(self, action: str, user_id: str = "", **kwargs):
        """记录用户操作"""
        message = f"用户操作 {action}"
        if user_id:
            message = f"用户[{user_id}] {action}"
        self.info(message, **kwargs)
    
    def set_level(self, level: int):
        """设置日志级别"""
        self.logger.setLevel(level)
        for handler in self.logger.handlers:
            handler.setLevel(level)
    
    def get_logger(self):
        """获取原始logger对象"""
        return self.logger


# 创建默认日志实例
def get_logger(name: str = "LongNovel", 
               log_file: str = "app.log",
               level: int = logging.INFO) -> Logger:
    """
    获取日志实例的便捷函数
    
    Args:
        name: 日志器名称
        log_file: 日志文件路径
        level: 日志级别
    
    Returns:
        Logger实例
    """
    return Logger(name=name, log_file=log_file, level=level)


# 创建不同用途的日志实例
def get_backend_logger() -> Logger:
    """获取后端专用日志器"""
    return get_logger(name="Backend", log_file="backend.log")

def get_frontend_logger() -> Logger:
    """获取前端专用日志器"""
    return get_logger(name="Frontend", log_file="frontend.log")

def get_api_logger() -> Logger:
    """获取API调用专用日志器"""
    return get_logger(name="API", log_file="api.log")

def get_error_logger() -> Logger:
    """获取错误专用日志器"""
    return get_logger(name="Error", log_file="error.log", level=logging.ERROR) 